package com.xy.network.base

import android.util.Log
import com.xy.network.bean.ResponseBean
import com.xy.network.commoninterceptor.CommonRequestInterceptor
import com.xy.network.commoninterceptor.CommonResponseInterceptor
import com.xy.network.environment.IEnvironment
import com.xy.network.errorhandler.ExceptionHandle
import com.xy.network.errorhandler.HttpErrorHandler
import io.reactivex.Observable
import io.reactivex.ObservableSource
import io.reactivex.ObservableTransformer
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.functions.Function
import io.reactivex.schedulers.Schedulers
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory

/**
 * @ClassName NetWorkApi
 * @Author xy
 * @Date 2021/8/17 17:03
 * @Description retrofit 网络请求封装
 */
abstract class NetWorkApi : IEnvironment {
    var compositeDisposable=CompositeDisposable()
    var environment = 0
    var baseUrl = "http://172.27.35.1:8080/"
    var iNekWorkRequireInfo: INekWorkRequireInfo? = null

    companion object {
        //保存retrofit
        private val retrofitHashMap = HashMap<String, Retrofit>()
    }

    //根据不同环境 切换域名
    protected constructor() {
        baseUrl = when (environment) {
            0 -> getTest()
            1 -> getNormal()
            else -> "http://172.27.35.1:8080/"
        }
    }


    //在application 中初始化获取App的版本信息，
    fun init(iNekWorkRequireInfo: INekWorkRequireInfo) {
        this.iNekWorkRequireInfo = iNekWorkRequireInfo
    }

    //获取retrofit
    fun getRetrofit(service: Class<*>): Retrofit? {
        val retrofitBuilder = Retrofit.Builder()
        if (retrofitHashMap[baseUrl + service.name] != null) {
            Log.i(
                "请求接口对象名称",
                "getRetrofit: $baseUrl+${service.name} +${retrofitHashMap[baseUrl + service.name]}"
            )
            return retrofitHashMap[baseUrl + service.name]
        }
        retrofitBuilder.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//rxjava 订阅
        retrofitBuilder.addConverterFactory(GsonConverterFactory.create())//Gosn 转换
        retrofitBuilder.baseUrl(baseUrl) //添加域名
        retrofitBuilder.client(getOkHttpClient()) //添加拦截器、打印日志
        var retrofit = retrofitBuilder.build()
        retrofitHashMap[baseUrl + service.name] = retrofit
        return retrofit
    }

//    //通过动态代理获取App 定义的接口
//    fun <T> getService(service: Class<T>): T? {
//        //动态代理
//        return getRetrofit(service)?.create(service)
//    }

    //获取OKHttp 设置监听器、日志输出
    private fun getOkHttpClient(): OkHttpClient {
        val okHttpClientBuilder = OkHttpClient.Builder()
        if (getInterceptor() != null) { //添加不同域名下的监听
            okHttpClientBuilder.addInterceptor(getInterceptor())
        }
        okHttpClientBuilder.addInterceptor(CommonRequestInterceptor())
        okHttpClientBuilder.addInterceptor(CommonResponseInterceptor())
        //判断是不是Debug模式
//        if (iNekWorkRequireInfo != null && iNekWorkRequireInfo?.isDebug()!!) {
        val httpLoggingInterceptor = HttpLoggingInterceptor()
        httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
        okHttpClientBuilder.addInterceptor(httpLoggingInterceptor)
//        }
        return okHttpClientBuilder.build()
    }

    //切换线程 ,避免每次都要执行io线程与主线程之间的切换
    fun <T> applySchedulers(observer: Observer<T>): ObservableTransformer<T, T> {
        return object : ObservableTransformer<T, T> {
            override fun apply(upstream: Observable<T>): ObservableSource<T> {
                val observable =
                    upstream.subscribeOn(Schedulers.io())//订阅
                        .observeOn(AndroidSchedulers.mainThread()) //观察
                        .map(getAppErrorMsgHandler<T>()) //添加自定义拦截错误
//                        .map(getAppErrorHandler<T>()) //拦截错误
                        .onErrorResumeNext(HttpErrorHandler<T>()) //拦截错误后进行处理 400 相关的错误会直接处理，
                observable.subscribe(observer)
                return observable
            }

        }
    }

    /**
     * 可能存在多个域名设置监听器
     * @return Interceptor
     */
    protected abstract fun getInterceptor(): Interceptor

    //错误信息监听
    protected abstract fun <T> getAppErrorMsgHandler(): Function<T, T>


    //错误信息转换  主要处理500相关的错误
    fun <T> getAppErrorHandler(): Function<T, T> {

        return Function<T, T> { response ->
            if (response is ResponseBean<*> && (response as ResponseBean<*>).code.isEmpty()) { //需要跟接口端对接,不同的域名下返回成功的标志不一样
                var exception = ExceptionHandle.ServerException()
                exception.code = response.code.toInt()
                exception.message = response.msg
                throw  exception  //抛出异常
            }
            response
        }
    }


}